/**
 * 用来控制 几何、网格等显示渲染的颜色、透明度、是否可见等操作
 *
 */
import { CSMesh } from '@amcax/base';
import { ctx2 } from '@app-base/module';
import { Renderer } from '@app-nextmesh/common/utils';
import { documentManager } from '@app-nextmesh/manager';
import { refreshCanvas } from './canvas';
import { makeWireframeDxid } from './model';
import { findModelInGroup } from './modelUtils';

const getGeometryId = (id: string) => {
  // GSP 存储的id会包含:s0等结尾，用来表示是solid(:s)/shell(:h)/face(:f)等的第几（0）个
  return id.split(':')[0];
};

const findModelInMeshGroup = (id: string) => {
  const meshGroup = ctx2.cadScene.meshGroup;
  return findModelInGroup(meshGroup, id);
};

/**
 * 更新几何/网格的颜色
 * @param color 颜色
 * @param ids 几何的id列表
 */
const updateModelsColor = (color: string, ids: string[]) => {
  for (let id of ids) {
    id = getGeometryId(id);
    const geometry = findModelInMeshGroup(id) as CSMesh;
    geometry?.material.color.set(color);
  }
  refreshCanvas();
};

const updateModelsVisible = (action: 'show' | 'hide') => {
  updateGeometriesVisible(action);
  updateMeshesVisible(action);
};

/**
 * 更新几何的可见性
 * @param action 操作
 * @param ids 几何的id列表，不传则作用于所有
 */
const updateGeometriesVisible = (
  action: 'show' | 'hide' | 'translucence',
  ids?: string[],
) => {
  const allIds = documentManager.getGeometriesId();
  ids = ids ?? allIds;
  for (let id of ids) {
    id = getGeometryId(id);
    if (!allIds.includes(id)) {
      continue;
    }
    const geometry = Renderer().getModelByDxid(id);
    if (!geometry) {
      continue;
    }
    let visible = true;
    let transparent: boolean = false;
    let opacity = 1;
    switch (action) {
      case 'show':
        visible = true;
        break;
      case 'hide':
        visible = false;
        break;
      case 'translucence':
        transparent = true;
        opacity = 0.75;
        break;
    }
    if (geometry.modelMesh) {
      geometry.modelMesh.visible = visible;
      if (geometry.modelMesh.material) {
        geometry.modelMesh.material.transparent = transparent;
        geometry.modelMesh.material.opacity = opacity;
      }
    }
    if (geometry.modelEdge) {
      geometry.modelEdge.visible = visible;
    }
    if (geometry.modelVertex) {
      geometry.modelVertex.visible = visible;
    }
    // 也把拾取的更新一下,这样和网格重叠时拾取不会被遮挡
    if (geometry.pickMesh) {
      geometry.pickMesh.visible = visible;
    }
    if (geometry.pickEdge) {
      geometry.pickEdge.visible = visible;
    }
    if (geometry.pickVertex) {
      geometry.pickVertex.visible = visible;
    }
  }

  refreshCanvas();
};

const updateGeometriesPolygon = (
  polygonOffset = false,
  polygonOffsetFactor = 0,
  polygonOffsetUnits = 0,
) => {
  const allIds = documentManager.getGeometriesId();
  for (const id of allIds) {
    const geometry = Renderer().getModelByDxid(id);
    if (!geometry) {
      continue;
    }
    if (geometry.modelMesh) {
      if (geometry.modelMesh.material) {
        geometry.modelMesh.material.polygonOffset = polygonOffset;
        geometry.modelMesh.material.polygonOffsetFactor = polygonOffsetFactor;
        geometry.modelMesh.material.polygonOffsetUnits = polygonOffsetUnits;
      }
    }
  }

  refreshCanvas();
};
/**
 * 更新网格的可见性
 * @param action 操作
 * @param ids 网格的id列表，不传则作用于所有
 */
const updateMeshesVisible = (
  action: 'show' | 'hide' | 'translucence' | 'wireframe',
  ids?: string[],
) => {
  const allIds = documentManager.getMeshesId();
  ids = ids ?? allIds;
  for (const id of ids) {
    if (!allIds.includes(id)) {
      continue;
    }
    const mesh = Renderer().getModelByDxid(id);
    if (!mesh) {
      continue;
    }
    let visibleWire = true;
    let visible = true;
    let transparent = false;
    let opacity = 1;
    switch (action) {
      case 'show':
        transparent = false;
        opacity = 1;
        break;
      case 'hide':
        visible = false;
        visibleWire = false;
        break;
      case 'translucence':
        transparent = true;
        opacity = 0.75;
        break;
      case 'wireframe':
        transparent = true;
        opacity = 0;
        break;
    }
    if (mesh.modelMesh) {
      mesh.modelMesh.visible = visible;
      if (mesh.modelMesh.material) {
        mesh.modelMesh.material.transparent = transparent;
        mesh.modelMesh.material.opacity = opacity;
      }
    }
    if (mesh.modelEdge) {
      mesh.modelEdge.visible = visible;
    }
    if (mesh.modelVertex) {
      mesh.modelVertex.visible = visible;
    }
    // 也把拾取的更新一下,这样和几何重叠时拾取不会被遮挡
    if (mesh.pickMesh) {
      mesh.pickMesh.visible = visible;
    }
    if (mesh.pickEdge) {
      mesh.pickEdge.visible = visible;
    }
    if (mesh.pickVertex) {
      mesh.pickVertex.visible = visible;
    }

    updateWireframeVisible(visibleWire, [id]);
  }

  refreshCanvas();
};

/**
 * 更新线框的可见性
 * @param visible 是否可见
 * @param ids 几何/网格的id列表，不传则作用于所有
 */
const updateWireframeVisible = (visible: boolean, ids?: string[]) => {
  ids = ids ?? [
    ...documentManager.getMeshesId(),
    ...documentManager.getGeometriesId(),
  ];
  for (const id of ids) {
    const wireframeModel = findModelInMeshGroup(makeWireframeDxid(id));
    if (wireframeModel) {
      wireframeModel.visible = visible;
    }
  }

  refreshCanvas();
};

export {
  updateGeometriesPolygon,
  updateGeometriesVisible,
  updateMeshesVisible,
  updateModelsColor,
  updateModelsVisible,
  updateWireframeVisible,
};
